package com.stellar.wechat.core.common;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
import com.stellar.wechat.core.common.exception.WxApiException;
import com.stellar.wechat.core.enums.WxErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URI;
import java.util.Map;

/**
 * @Author Jqcc
 * @Version 1.0
 * @Data 2025/3/30
 * @Description 微信http客户端: 提供发送http请求的能力
 */
@Slf4j
@Component
public class WxHttpClient {

    private final CloseableHttpClient httpClient;

    private final ObjectMapper objectMapper;

    private static final Map<Integer, WxErrorCode> ERROR_CODE_MAPPING =
            ImmutableMap.<Integer, WxErrorCode>builder()
                    .put(40029, WxErrorCode.INVALID_CODE)
                    .put(45011, WxErrorCode.TOO_FREQUENT)
                    .put(40001, WxErrorCode.INVALID_ACCESS_TOKEN)
                    .put(40003, WxErrorCode.INVALID_OPENID)
                    .put(87009, WxErrorCode.INVALID_SIGNATURE)
                    .put(87007, WxErrorCode.SESSION_KEY_EXPIRED_OR_NOT_EXIST)
                    .put(43101, WxErrorCode.TEMPLATE_MSG_ERROR)
                    .build();

    public WxHttpClient(CloseableHttpClient httpClient, ObjectMapper objectMapper) {
        this.httpClient = httpClient;
        this.objectMapper = objectMapper;
    }

    public <T> T get(URI uri, Class<T> responseType) throws IOException, WxApiException {
        try (CloseableHttpResponse response = httpClient.execute(new HttpGet(uri))) {
            return handleResponse(response, responseType);
        }
    }

    public <T> T post(URI uri, Object requestBody, Class<T> responseType) throws IOException, WxApiException {
        HttpPost httpPost = new HttpPost(uri);
        httpPost.setEntity(new StringEntity(objectMapper.writeValueAsString(requestBody)));
        httpPost.setHeader("Content-Type", "application/json");

        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            return handleResponse(response, responseType);
        }
    }

    private <T> T handleResponse(CloseableHttpResponse response, Class<T> type)
            throws IOException, WxApiException {
        JsonNode root = objectMapper.readTree(response.getEntity().getContent());
        if (root.has("errcode") && root.get("errcode").asInt() != 0) {
            log.error("微信接口调用失败: {}", root);
            WxErrorCode errorCode = ERROR_CODE_MAPPING.get(root.get("errcode").asInt());
            throw new WxApiException(errorCode);
        }
        return objectMapper.treeToValue(root, type);
    }
}